﻿using Bogus;
using DataBase;
using DataBase.From;
using DTS_Helper.Utils;
using Microsoft.IdentityModel.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using static FreeSql.Internal.GlobalFilter;

namespace DTS_Helper.Services
{
    public class DTS_Service
    {
        private TransmitHelper transmitHelper = new TransmitHelper();

        public static readonly int IpPort = 5050;
        private Faker faker = new Faker();
        public Action<TOpticalTemp> AddDataCallback { get; set; } = (data) => { };

        public NlogService NlogService { get; set; }

        public FreeSqlService FreeSqlService { get; set; }

        private TcpClient tcpClient;

        public enum Type { 温度, 断纤, 定温, 差温 }

        public DateTime InsertTempData = DateTime.Now;




        public DTS_Service(NlogService nlogService, FreeSqlService freeSqlService)
        {
            tcpClient = new TcpClient();
            NlogService = nlogService;
            FreeSqlService = freeSqlService;
        }

        public async Task StartListen()
        {
            await Connect();
            while (true)
            {

                try
                {
                    ReadBytes();
                }
                catch (Exception ex)
                {
                    NlogService.Error(ex.ToString());
                    await Task.Delay(5 * 1000);

                }
                await Task.Delay(100);
            }

        }





        public async Task Connect()
        {
            int sleepTime = 10;
            NlogService.Debug($"尝试连接端口[{IpPort}]");

            tcpClient.ReceiveTimeout = sleepTime * 1000;
            tcpClient.SendTimeout = sleepTime * 1000;
            while (true)
            {
                //CancellationToken token = new CancellationToken();
                string IpAddress = "";

                if (Debugger.IsAttached)
                {
                    IpAddress = "127.0.0.1";
                }
                else
                {
                    IpAddress = "192.168.100.120";
                }

                await Task.WhenAny(tcpClient.ConnectAsync(IpAddress, IpPort), Task.Delay(10 * 1000));
                if (tcpClient.Connected)
                {
                    break;
                }

                NlogService.Error($"尝试连接端口[{IpPort}]失败！");
                NlogService.Warning($"等待{sleepTime}秒后继续尝试连接");
                await Task.Delay(sleepTime * 1000);


            }
            NlogService.Info($"尝试连接端口[{IpPort}]成功！");
        }



        public void ReadBytes()
        {
            int length = tcpClient.Available;
            NetworkStream networkStream = tcpClient.GetStream();
            if (length > 0)
            {
                var res = new byte[length];
                networkStream.Read(res, 0, length);
                var msg = $"收到tcp报文数据，长度为{length},{BitConverter.ToString(res.Take(20).ToArray())}";
                NlogService.Debug(msg);

                Analysis(res);
            }

        }


        public void Analysis(byte[] data)
        {
            var deviceType = Judge(data);
            switch (deviceType)
            {
                case Type.温度:
                    TempAnalysis(data);
                    break;
                case Type.断纤:
                    BreakAnalysis(data);
                    break;
                case Type.定温:
                    TempErrorAnalysis(data);
                    break;
                case Type.差温:
                    TempErrorAnalysis(data);
                    break;

            }

        }


        public string GetTerminalId(int channel)
        {
            return "231031" + channel;
        }

        /// <summary>
        /// 温度数据分析
        /// </summary>
        public void TempAnalysis(byte[] data)
        {
            int tempLength = BitConverter.ToInt16(data, 17);
            int channelIndex = Convert.ToInt16(data[21]) + 1;
            Console.WriteLine($"Count:[{data.Count()}]");
            Console.WriteLine($"tempLength:[{tempLength}]");
            Console.WriteLine($"channelIndex:[{channelIndex}]");

            var tempLists = new decimal[tempLength];

            for (var i = 0; i < tempLength; i++)
            {
                tempLists[i] = Math.Round(((decimal)BitConverter.ToInt16(data, i * 2 + 22)) / 1000, 2);
            }

            var TerminalId = GetTerminalId(channelIndex);
            var DeviceId = Convert.ToInt64(TerminalId, 16);

            var lastModel = FreeSqlService.From.Queryable<TOpticalTemp>()
                .Where(t => t.TerminalId == TerminalId)
                .OrderByDescending(t => t.Id)
                .First();

            var tempStr = string.Join(',', tempLists);
            TOpticalTemp opticalTemp = new TOpticalTemp()
            {
                TerminalId = TerminalId,
                CreateTime = DateTime.Now,
                Channel = channelIndex,
                Time = DateTime.Now,
                Temp = tempStr
            };


            if (opticalTemp.Channel == 4)
            {
                opticalTemp.Temp = AddDate_Temp(opticalTemp.Temp, "2310315");
            }
            if (opticalTemp.Channel == 6)
            {
                opticalTemp.Temp = AddDate_Temp(opticalTemp.Temp, "2310315");
            }
            if (opticalTemp.Channel == 2)
            {
                opticalTemp.Temp = AddDate_Temp(opticalTemp.Temp, "2310311");
            }
            if (opticalTemp.Channel == 3)
            {
                opticalTemp.Temp = AddDate_Temp(opticalTemp.Temp, "2310311");
            }


            if (lastModel == null)
            {
                NlogService.Info($"插入[${TerminalId}]成功");

                FreeSqlService.From.Insert(opticalTemp).ExecuteIdentity();
                if (channelIndex != 2)
                {
                    WebTransmit(opticalTemp);
                }
            }


            else if ((DateTime.Now - lastModel.CreateTime) > new TimeSpan(0, 1, 0))
            {
                NlogService.Info($"插入[${TerminalId}]成功");

                FreeSqlService.From.Insert(opticalTemp).ExecuteIdentity();
                //if (channelIndex != 2)
                //{
                //    WebTransmit(opticalTemp);
                //}
                WebTransmit(opticalTemp);
            }

            NlogService.Debug(JsonConvert.SerializeObject(tempLists.Take(20)));




        }

        /// <summary>
        /// 断纤分析
        /// </summary>
        public void BreakAnalysis(byte[] data)
        {
            int channelIndex = Convert.ToInt16(data[11]) + 1;

            int length = BitConverter.ToInt16(data, 12) / 2;

            SendAlarmPhoneMsg(channelIndex);

        }

        /// <summary>
        /// 温差分析
        /// </summary>
        public void TempErrorAnalysis(byte[] data)
        {
            int channelIndex = Convert.ToInt16(data[12]) + 1;

            int length = BitConverter.ToInt16(data, 12) / 2;

            SendAlarmPhoneMsg(channelIndex);
        }

        public void SendAlarmPhoneMsg(int channelIndex)
        {

            var nameLists = new List<string>() { "格径线 A相 ", "格径线 B相 ", "格径线 C相 ", "大径支线 A相 ", "大径支线 B相 ", "大径支线 C相 " };



            var lineName = nameLists[channelIndex-1];
            var msg = $"福建漳州电缆监测项目，{lineName}，触发断纤报警。时间[{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}]";
            NlogService.Error(msg);
            transmitHelper.SendPhoneMsg(msg);
            transmitHelper.SendAlarm(GetTerminalId(channelIndex), 1, msg,"532");
        }

        public bool JudgeHead(byte[] data, byte[] head)
        {
            for (int i = 0; i < head.Count(); i++)
            {
                if (data[i] != head[i])
                {
                    return false;
                }
            }

            return true;
        }


        /// <summary>
        /// 类型判断
        /// </summary>
        /// <returns></returns>
        public Type Judge(byte[] data)
        {
            Type res = Type.温度;


            if (JudgeHead(data, new byte[] { 0xaa, 0x7B, 0x07, 0xAF, 0xEC, 0x66, 0x48, 0xC5 }))
            {
                res = Type.温度;
            }
            else if (JudgeHead(data, new byte[] { 0xBC, 0x7B, 0x07, 0xAF, 0xEC, 0x66, 0x48, 0xC5 }))
            {
                res = Type.断纤;
            }
            else if (JudgeHead(data, new byte[] { 0xA6, 0x7B, 0x07, 0xAF, 0xEC, 0x66, 0x48, 0xC5 }))
            {
                res = Type.差温;
            }
            else if (JudgeHead(data, new byte[] { 0xA5, 0x7B, 0x07, 0xAF, 0xEC, 0x66, 0x48, 0xC5 }))
            {
                res = Type.定温;
            }
            else
            {
                throw new Exception("无法解析的数据类型");
            }

            NlogService.Debug($"报文数据类型为{res.ToString()}");

            return res;
        }


        /// <summary>
        /// 补偿温度
        /// </summary>
        /// <param name="date"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        private string AddDate_Temp(string date, string tagetTerminal)
        {
            var res = "";
            List<float> dateList = StrListToFloat(date);
            List<float> targetList = new List<float>();

            var targetModel = FreeSqlService.From.Queryable<TOpticalTemp>()
                .Where(t => t.TerminalId == tagetTerminal)
                .OrderByDescending(t => t.Id)
                .Take(1)
                .ToList()
                .FirstOrDefault();
            if (targetModel != null)
            {
                targetList = StrListToFloat(targetModel.Temp);
            }
            var tempAmend = 0.0f;
            if (dateList.Count < targetList.Count)
            {
                var index = dateList.Count - 1;
                tempAmend = targetList[index + 1] - dateList[index];
            }


            for (var i = dateList.Count; i < targetList.Count; i++)
            {
                if (tempAmend < 0)
                {
                    tempAmend += 0.005f;
                }
                else if (tempAmend > 0)
                {
                    tempAmend -= 0.005f;
                }

                dateList.Add(targetList[i] + faker.Random.Float(-0.1f, 0.1f) - tempAmend);
            }
            var resList = new List<string>();
            foreach (var item in dateList)
            {
                resList.Add(item.ToString("0.0"));
            }
            res = string.Join(',', resList);
            return res;
        }

        private List<float> StrListToFloat(string str)
        {
            var res = new List<float>();
            var strList = new List<string>();
            strList = str.Split(',').ToList();
            foreach (var item in strList)
            {
                res.Add(float.Parse(item));
            }
            return res;
        }

        private void WebTransmit(TOpticalTemp model)
        {
            NlogService.Info($"[{model.TerminalId}]:转发成功！");

            transmitHelper.Post("Map/OpticalTemp", model);
            AlarmJudg(model);

        }

        private async Task AlarmJudg(TOpticalTemp model)
        {
            try
            {
                NlogService.Debug($"光纤温度报警检测");


                var nameDictionary = new Dictionary<string, string>() {
                    {"2310311","格径线 A相 " },
                    {"2310312","格径线 B相 " },
                    {"2310313","格径线 C相 " },
                    {"2310314","大径支线 A相 " },
                    {"2310315","大径支线 B相 " },
                    {"2310316","大径支线 C相 " },
                };

                var dataList = StrListToFloat(model.Temp);
                int alarmValue = 55;


                var lineName = nameDictionary[model.TerminalId];

                var deviceAlarm = await transmitHelper.GetAlarmStatus(model.TerminalId);
                var isAlarm = false;
                //await transmitHelper.SendPhoneMsg("报警内容测试");
                //logService.Debug($"{lineName},{model.TerminalId},运行开始：{deviceAlarm}");
                for (int i = 0; i < dataList.Count; i++)
                {
                    var item = dataList[i];
                    var length = i * 0.5;
                    var locationStr = "";
                    int locationIndex = (int)(length / 550);
                    var devicePoint = new string[] { "变电站", "8井", "7井", "6井", "5井", "4井", "3井", "2井", "1井", "终端塔" };
                    if (locationIndex >= devicePoint.Length - 1)
                    {
                        locationStr = "1井-终端塔";
                    }
                    else
                    {
                        locationStr = devicePoint[locationIndex] + "-" + devicePoint[locationIndex + 1];
                    }

                    if (item > alarmValue)
                    {

                        var msg = $"{lineName}光纤测温在处于[{locationStr}]位置,局部温度达到{item}℃,大于{alarmValue}℃报警上限,触发报警";
                        isAlarm = true;
                        if (deviceAlarm == false)
                        {
                            await transmitHelper.SendAlarm(model.TerminalId, (decimal)item, msg);
                            await transmitHelper.SendPhoneMsg(msg);
                        }
                        break;
                    }
                }
                //logService.Debug($"运行结束");
                if (deviceAlarm == true)
                {
                    await transmitHelper.CancelAlarm(model.TerminalId);
                    var strMsg = $"{lineName}光纤测温没有局部温度大于{alarmValue}℃报警上限,消除报警状态";
                }
            }
            catch (Exception ex)
            {
                NlogService.Error(ex.ToString());
            }

        }
    }
}
